/**
* File: War3Source_Dean_Winchester.sp
* Description: The Dean Winchester race for SourceCraft.
* Author(s): xDr.HaaaaaaaXx
*/

#pragma semicolon 1
#include <sourcemod>
#include <sdktools>
#include <sdktools_stocks>
#include <sdktools_tempents>
#include <sdktools_functions>
#include <sdktools_tempents_stocks>
#include <sdktools_entinput>
#include <sdktools_sound>
#include <haaaxfunctions>

//#include "W3SIncs/War3Source_Interface"

// War3Source stuff
new thisRaceID, SKILL_COLT, SKILL_WATER, SKILL_RESP, SKILL_EVADE, ULT_DUEL;

// Chance/Data Arrays
// skill 1
new Float:DamageMultiplier[6] = { 0.0, 0.5, 1.0, 1.5, 2.0, 2.5 };
new PhysRingSprite;

// skill 2
new Float:WaterChance[6] = { 0.0, 0.1, 0.15, 0.2, 0.25, 0.3 };
new String:WaterSound[] = "ambient/wind/wind_snippet2.wav";
new FunnelSprite;

// skill 3
new Float:SpawnChance[6] = { 0.0, 0.15, 0.20, 0.25, 0.30, 0.35 };
new Float:death_pos[MAXPLAYERS][3];

// skill 4
new Float:EvadeChance[6] = { 0.0, 0.11, 0.15, 0.22, 0.26, 0.30 };
new PupilSprite;

// skill 5
new bool:bClientInDuel[MAXPLAYERS];
new ClientTarget[MAXPLAYERS];
new bool:bDuelActived;
new Float:LastDuelTime;

// Other
new m_iFOV;

public Plugin:myinfo = 
{
	name = "War3Source Race - Dean Winchester",
	author = "xDr.HaaaaaaaXx",
	description = "The Dean Winchester race for War3Source.",
	version = "1.0.0.0",
	url = ""
};

public OnPluginStart()
{
	HookEvent( "player_death", PlayerDeathEvent );
	HookEvent( "round_end", RoundEndEvent );
	m_iFOV = FindSendPropInfo( "CBasePlayer", "m_iFOV" );
	CreateTimer( 0.1, CheckDuel, _, TIMER_REPEAT );
}

public OnMapStart()
{
	PhysRingSprite = PrecacheModel( "sprites/physring1.vmt" );
	PupilSprite = PrecacheModel( "models/alyx/pupil_r.vmt" );
	FunnelSprite = PrecacheModel( "models/effects/portalfunnel.mdl" );
	War3_PrecacheSound( WaterSound );
}

public OnWar3PluginReady()
{
	thisRaceID = War3_CreateNewRace( "Dean Winchester", "winchesterd" );
	
	SKILL_COLT = War3_AddRaceSkill( thisRaceID, "Colt", "More Damage", false, 5 );
	SKILL_WATER = War3_AddRaceSkill( thisRaceID, "Holy Water", "Shake Demon", false, 5 );
	SKILL_RESP = War3_AddRaceSkill( thisRaceID, "Contract With a Demon", "Respawn", false, 5 );
	SKILL_EVADE = War3_AddRaceSkill( thisRaceID, "Rabbit Foot", "Get Luck and Change to Evade Bullets", false, 5 );
	ULT_DUEL = War3_AddRaceSkill( thisRaceID, "Demon Trap", "Trap Demon and Take Duel With Him", true, 5 );
	
	W3SkillCooldownOnSpawn( thisRaceID, ULT_DUEL, 15.0 );
	
	War3_CreateRaceEnd( thisRaceID );
}

public OnRaceChange( client, oldrace, newrace )
{
	if( newrace != thisRaceID )
	{
		War3_WeaponRestrictTo( client, thisRaceID, "" );
		W3ResetAllBuffRace( client, thisRaceID );
	}
	else
	{
		War3_WeaponRestrictTo( client, thisRaceID, "weapon_knife,weapon_deagle" );
		if( IsPlayerAlive( client ) )
		{
			StripWeaponFromClient( client );
			GivePlayerItem( client, "weapon_deagle" );
			GivePlayerItem( client, "weapon_knife" );
		}
	}
}

public OnWar3EventSpawn( client )
{
	new race = War3_GetRace( client );
	if( race == thisRaceID )
	{
		War3_WeaponRestrictTo( client, thisRaceID, "weapon_deagle,weapon_knife" );
		StripWeaponFromClient( client );
		
		GivePlayerItem( client, "weapon_deagle" );
		GivePlayerItem( client, "weapon_knife" );
	}
	else
	{
		War3_WeaponRestrictTo( client, thisRaceID, "" );
	}
	bClientInDuel[client] = false;
	W3SetPlayerColor( client, thisRaceID, 255, 255, 255, _, GLOW_DEFAULT );
}

public OnWar3EventDeath( victim, attacker )
{
	if( War3_GetRace( victim ) == thisRaceID )
	{
		War3_WeaponRestrictTo( victim, thisRaceID, "weapon_deagle,weapon_knife" );
	}
	else
	{
		War3_WeaponRestrictTo( victim, thisRaceID, "" );
	}
	W3ResetAllBuffRace( victim, thisRaceID );
	
	if( bClientInDuel[victim] && bClientInDuel[attacker] )
	{
		bDuelActived = false;
		
		new String:ClientName[32];
		
		GetClientName( attacker, ClientName, 32 );
		
		PrintCenterTextAll( "!.:%s WiN:.!", ClientName );
	}
	if( bClientInDuel[victim] )
	{
		bDuelActived = false;
	}
	
	W3SetPlayerColor( ClientTarget[victim], thisRaceID, 255, 255, 255, _, GLOW_DEFAULT );
	W3SetPlayerColor( victim, thisRaceID, 255, 255, 255, _, GLOW_DEFAULT );
	
	bClientInDuel[ClientTarget[victim]] = false;
	bClientInDuel[victim] = false;
	
	ClientTarget[ClientTarget[victim]] = 0;
	ClientTarget[victim] = 0;
}

public OnWar3EventPostHurt( victim, attacker, damage )
{
	if( W3GetDamageIsBullet() && ValidPlayer( victim, true ) && ValidPlayer( attacker, true ) && GetClientTeam( victim ) != GetClientTeam( attacker ) )
	{
		if( War3_GetRace( attacker ) == thisRaceID )
		{
			new skill_colt = War3_GetSkillLevel( attacker, thisRaceID, SKILL_COLT );
			if( !Hexed( attacker, false ) && GetRandomFloat( 0.0, 1.0 ) <= 0.15 )
			{
				if( !W3HasImmunity( victim, Immunity_Skills ) )
				{
					War3_DealDamage( victim, RoundToFloor( damage * DamageMultiplier[skill_colt] ), attacker, DMG_BULLET, "weapon_colt" );
				
					W3PrintSkillDmgHintConsole( victim, attacker, War3_GetWar3DamageDealt(), SKILL_COLT );
					
					new Float:pos[3];
					
					GetClientAbsOrigin( victim, pos );
					
					pos[2] += 15;
					
					TE_SetupGlowSprite( pos, PhysRingSprite, 3.0, 2.0, 255 );
					TE_SendToAll();
				}
			}
		}
		if( War3_GetRace( attacker ) == thisRaceID )
		{
			new skill_water = War3_GetSkillLevel( attacker, thisRaceID, SKILL_WATER );
			if( !Hexed( attacker, false ) && GetRandomFloat( 0.0, 1.0 ) <= WaterChance[skill_water] )
			{
				if( !W3HasImmunity( victim, Immunity_Skills ) )
				{
					new Float:pos[3];
					
					GetClientAbsOrigin( victim, pos );
					
					TE_SetupGlowSprite( pos, FunnelSprite, 3.0, 5.0, 255 );
					TE_SendToAll();
					
					W3FlashScreen( victim, { 215, 25, 251, 75 }, 0.3, 0.3 );
					
					EmitSoundToAll( WaterSound, attacker );
					EmitSoundToAll( WaterSound, victim );
					
					SetEntData( victim, m_iFOV, 500 );
					CreateTimer( 0.1, StopFov, victim );
				}
			}
		}
	}
}

public Action:StopFov( Handle:timer, any:client )
{
	if( ValidPlayer( client, true ) )
	{
		SetEntData( client, m_iFOV, 0 );
	}
}

public PlayerDeathEvent( Handle:event, const String:name[], bool:dontBroadcast )
{
	new client = GetClientOfUserId( GetEventInt( event, "userid" ) );
	if( War3_GetRace( client ) == thisRaceID && client != 0 )
	{
		new skill_spawn = War3_GetSkillLevel( client, thisRaceID, SKILL_RESP );
		if( skill_spawn > 0 && GetRandomFloat( 0.0, 1.0 ) <= SpawnChance[skill_spawn] )
		{
			new Float:pos[3];
			
			GetClientAbsOrigin( client, death_pos[client] );
			GetClientAbsOrigin( client, pos );
			
			CreateTimer( 2.0, Spawn, client );
			CreateTimer( 2.1, Teleport, client );
		}
	}
}

public RoundEndEvent( Handle:event, const String:name[], bool:dontBroadcast )
{
	if( bDuelActived )
	{
		bDuelActived = false;
	}
}

public Action:Spawn( Handle:timer, any:client )
{
	if( ValidPlayer( client, true ) )
	{
		War3_SpawnPlayer( client );
		PrintToChat( client, "\x05: \x03You have ecaped from \x04Hell!" );
	}
}

public Action:Teleport( Handle:timer, any:client )
{
	if( ValidPlayer( client, true ) )
	{
		TeleportEntity( client, death_pos[client], NULL_VECTOR, NULL_VECTOR );
	}
}

public OnW3TakeDmgBullet( victim, attacker, Float:damage )
{
	if( IS_PLAYER( victim ) && IS_PLAYER( attacker ) && victim > 0 && attacker > 0 && attacker != victim )
	{
		new vteam = GetClientTeam( victim );
		new ateam = GetClientTeam( attacker );
		if( vteam != ateam )
		{
			new race_victim = War3_GetRace( victim );
			new skill_level = War3_GetSkillLevel( victim, thisRaceID, SKILL_EVADE );
			if( race_victim == thisRaceID && skill_level > 0 && GetRandomFloat( 0.0, 1.0 ) <= EvadeChance[skill_level] )
			{
				if( !W3HasImmunity( attacker, Immunity_Skills ) )
				{
					War3_DamageModPercent( 0.0 );
					W3MsgEvaded( victim, attacker );
					
					new Float:pos[3];
					
					GetClientAbsOrigin( victim, pos );
					
					pos[2] += 15;
					
					TE_SetupGlowSprite( pos, PupilSprite, 3.0, 3.0, 255 );
					TE_SendToAll();
				}
				else
				{
					W3MsgEnemyHasImmunity( victim, true );
				}
			}
		}
	}
}

public OnW3TakeDmgAll( victim, attacker, Float:damage )
{
	if( IS_PLAYER( victim ) && IS_PLAYER( attacker ) && victim > 0 && attacker > 0 && attacker != victim )
	{
		new vteam = GetClientTeam( victim );
		new ateam = GetClientTeam( attacker );
		if( vteam != ateam )
		{
			if( bClientInDuel[victim] && !bClientInDuel[attacker] )
			{
				War3_DamageModPercent( 0.0 );
			}
			if( !bClientInDuel[victim] && bClientInDuel[attacker] )
			{
				War3_DamageModPercent( 0.0 );
			}
		}
	}
}

public OnUltimateCommand( client, race, bool:pressed )
{
	if( race == thisRaceID && pressed && IsPlayerAlive( client ) && !Silenced( client ) )
	{
		new ult_level = War3_GetSkillLevel( client, race, ULT_DUEL );
		if( ult_level > 0 )
		{
			if( War3_SkillNotInCooldown( client, thisRaceID, ULT_DUEL, true ) )
			{
				if( !bDuelActived )
				{
					bDuelActived = true;
					Duel( client );
				}
			}
		}
		else
		{
			W3MsgUltNotLeveled( client );
		}
	}
}

stock Duel( client )
{
	ClientTarget[client] = 0;
	
	if( GetClientTeam( client ) == TEAM_T )
		ClientTarget[client] = War3_GetRandomPlayer( "#ct", true, true );
	if( GetClientTeam( client ) == TEAM_CT )
		ClientTarget[client] = War3_GetRandomPlayer( "#t", true, true );
	
	if( ClientTarget[client] == 0 )
	{
		PrintHintText( client, "No Target Found" );
	}
	else
	{
		new target = ClientTarget[client];
		ClientTarget[target] = client;
		bClientInDuel[target] = true;
		bClientInDuel[client] = true;
		
		new String:ClientTargetName[32];
		new String:ClientName[32];
		
		GetClientName( target, ClientTargetName, 32 );
		GetClientName( client, ClientName, 32 );
		
		SetEntityHealth( target, 100 );
		SetEntityHealth( client, 100 );
		
		PrintToChat( target, "\x05: \x04%s \x03has challanged you to a duel \x04Fight in 3 seconds", ClientName );
		PrintToChat( client, "\x05: \x03You have Challanged \x04%s \x03to a Duel", ClientTargetName );
		
		StripWeaponFromClient( target );
		StripWeaponFromClient( client );
		
		War3_WeaponRestrictTo( target, thisRaceID, "weapon_knife" );
		War3_WeaponRestrictTo( client, thisRaceID, "weapon_knife" );
		
		PrintCenterTextAll( "!%s .:vs:. %s!", ClientName, ClientTargetName );
		
		W3SetPlayerColor( target, thisRaceID, 0, 0, 0, _, GLOW_DEFAULT );
		W3SetPlayerColor( client, thisRaceID, 0, 0, 0, _, GLOW_DEFAULT );
		
		CreateTimer( 3.0, Print3, client );
		CreateTimer( 4.0, Print2, client );
		CreateTimer( 5.0, Print1, client );
		CreateTimer( 6.0, GiveDeagle, client );
		
		LastDuelTime = GetGameTime();
		
		War3_CooldownMGR( client, 25.0, thisRaceID, ULT_DUEL );
	}
}

public Action:Print3( Handle:timer, any:client )
{
	PrintCenterTextAll( "3" );
}

public Action:Print2( Handle:timer, any:client )
{
	PrintCenterTextAll( "2" );
}

public Action:Print1( Handle:timer, any:client )
{
	PrintCenterTextAll( "1" );
}

public Action:GiveDeagle( Handle:timer, any:client )
{
	if( ValidPlayer( ClientTarget[client], true ) )
	{
		War3_WeaponRestrictTo( ClientTarget[client], thisRaceID, "weapon_deagle,weapon_knife" );
		GivePlayerItem( ClientTarget[client], "weapon_deagle" );
		GivePlayerItem( ClientTarget[client], "weapon_knife" );
	}
	
	if( ValidPlayer( client, true ) )
	{
		War3_WeaponRestrictTo( client, thisRaceID, "weapon_deagle,weapon_knife" );
		GivePlayerItem( client, "weapon_deagle" );
		GivePlayerItem( client, "weapon_knife" );
	}
	
	PrintCenterTextAll( ".:FighT:." );
}

public Action:CheckDuel( Handle:timer, any:___ )
{
	if( LastDuelTime < GetGameTime() - 36 && bDuelActived )
	{
		bDuelActived = false;
		PrintCenterTextAll( ".:DraW:." );
		for( new i = 1; i <= MaxClients; i++ )
		{
			if( ValidPlayer( i ) )
			{
				if( bClientInDuel[i] )
				{
					bClientInDuel[i] = false;
					ClientTarget[i] = 0;
					W3SetPlayerColor( i, thisRaceID, 255, 255, 255, _, GLOW_DEFAULT );
				}
			}
		}
	}
	new bool:bDuelActivedCheck = false;
	for( new i = 1; i <= MaxClients; i++ )
	{
		if( ValidPlayer( i ) )
		{
			if( bClientInDuel[i] )
			{
				bDuelActivedCheck = true;
				break;
			}
		}
	}
	if( !bDuelActivedCheck )
	{
		bDuelActived = false;
	}
}